<html lang="zh">
<head>
	<meta charset="utf-8">
	<title>jquery大雪花背景动画特效代码 - 代码库</title>
	<script src="/js/jquery.min.js"></script>
	<script src="/js/dmaku.js"></script>
	<style>
		html,body{width:100%;height:100%;margin:0;padding:0;overflow:hidden}
		.container{width:100%;height:100%;margin:0;padding:0}
	</style>
</head>

<body>
<div id="jsi-snow-container" class="container" style="position: fixed">

</div>

<script type="application/javascript">
	var RENDERER = {
		SNOW_COUNT: {INIT : 100, DELTA : 1},
		BACKGROUND_COLOR : 'hsl(%h, 50%, %l%)',
		INIT_HUE : 180,
		DELTA_HUE : 0.1,

		init : function(){
			this.setParameters();
			this.reconstructMethod();
			this.createSnow(this.SNOW_COUNT.INIT * this.countRate, true);
			this.render();
		},
		setParameters : function(){
			this.$window = $(window);

			this.$container = $('#jsi-snow-container');
			this.width = this.$container.width();
			this.height = this.$container.height();
			this.center = {x : this.width / 2, y : this.height / 2};
			this.countRate =  this.width * this.height / 500 / 500;
			this.canvas = $('<canvas />').attr({width : this.width, height : this.height}).appendTo(this.$container).get(0);
			this.context = this.canvas.getContext('2d');

			this.radius = Math.sqrt(this.center.x * this.center.x + this.center.y * this.center.y);
			this.hue = this.INIT_HUE;
			this.snows = [];
		},
		reconstructMethod : function(){
			this.render = this.render.bind(this);
		},
		createSnow : function(count, toRandomize){
			for(var i = 0; i < count; i++){
				this.snows.push(new SNOW(this.width, this.height, this.center, toRandomize));
			}
		},
		render : function(){
			requestAnimationFrame(this.render);

			var gradient = this.context.createRadialGradient(this.center.x, this.center.y, 0, this.center.x, this.center.y, this.radius),
					backgroundColor = this.BACKGROUND_COLOR.replace('%h', this.hue);

			gradient.addColorStop(0, backgroundColor.replace('%l', 30));
			gradient.addColorStop(0.2, backgroundColor.replace('%l', 20));
			gradient.addColorStop(1, backgroundColor.replace('%l', 5));

			this.context.fillStyle = gradient;
			this.context.fillRect(0, 0, this.width, this.height);

			for(var i = this.snows.length - 1; i >= 0; i--){
				if(!this.snows[i].render(this.context)){
					this.snows.splice(i, 1);
				}
			}
			this.hue += this.DELTA_HUE;
			this.hue %= 360;

			this.createSnow(this.SNOW_COUNT.DELTA, false);
		}
	};
	var SNOW = function(width, height, center, toRandomize){
		this.width = width;
		this.height = height;
		this.center = center;
		this.init(toRandomize);
	};
	SNOW.prototype = {
		RADIUS : 20,
		OFFSET : 4,
		INIT_POSITION_MARGIN : 20,
		COLOR : 'rgba(255, 255, 255, 0.8)',
		TOP_RADIUS : {MIN : 1, MAX : 3},
		SCALE : {INIT : 0.04, DELTA : 0.01},
		DELTA_ROTATE : {MIN : -Math.PI / 180 / 2, MAX : Math.PI / 180 / 2},
		THRESHOLD_TRANSPARENCY : 0.7,
		VELOCITY : {MIN : -1, MAX : 1},
		LINE_WIDTH : 2,
		BLUR : 10,

		init : function(toRandomize){
			this.setParameters(toRandomize);
			this.createSnow();
		},
		setParameters : function(toRandomize){
			if(!this.canvas){
				this.radius = this.RADIUS + this.TOP_RADIUS.MAX * 2 + this.LINE_WIDTH;
				this.length = this.radius * 2;
				this.canvas = $('<canvas />').attr({width : this.length, height : this.length}).get(0);
				this.context = this.canvas.getContext('2d');
			}
			this.topRadius = this.getRandomValue(this.TOP_RADIUS);

			var theta = Math.PI * 2 * Math.random();

			this.x = this.center.x + this.INIT_POSITION_MARGIN * Math.cos(theta);
			this.y = this.center.y + this.INIT_POSITION_MARGIN * Math.sin(theta);
			this.vx = this.getRandomValue(this.VELOCITY);
			this.vy = this.getRandomValue(this.VELOCITY);

			this.deltaRotate = this.getRandomValue(this.DELTA_ROTATE);
			this.scale = this.SCALE.INIT;
			this.deltaScale = 1 + this.SCALE.DELTA * 500 / Math.max(this.width, this.height);
			this.rotate = 0;

			if(toRandomize){
				for(var i = 0, count = Math.random() * 1000; i < count; i++){
					this.x += this.vx;
					this.y += this.vy;
					this.scale *= this.deltaScale;
					this.rotate += this.deltaRotate;
				}
			}
		},
		getRandomValue : function(range){
			return range.MIN + (range.MAX - range.MIN) * Math.random();
		},
		createSnow : function(){
			this.context.clearRect(0, 0, this.length, this.length);

			this.context.save();
			this.context.beginPath();
			this.context.translate(this.radius, this.radius);
			this.context.strokeStyle = this.COLOR;
			this.context.lineWidth = this.LINE_WIDTH;
			this.context.shadowColor = this.COLOR;
			this.context.shadowBlur = this.BLUR;

			var angle60 = Math.PI / 180 * 60,
					sin60 = Math.sin(angle60),
					cos60 = Math.cos(angle60),
					threshold = Math.random() * this.RADIUS / this.OFFSET | 0,
					rate = 0.5 + Math.random() * 0.5,
					offsetY = this.OFFSET * Math.random() * 2,
					offsetCount = this.RADIUS / this.OFFSET;

			for(var i = 0; i < 6; i++){
				this.context.save();
				this.context.rotate(angle60 * i);

				for(var j = 0; j <= threshold; j++){
					var y = -this.OFFSET * j;

					this.context.moveTo(0, y);
					this.context.lineTo(y * sin60, y * cos60);
				}
				for(var j = threshold; j < offsetCount; j++){
					var y = -this.OFFSET * j,
							x = j * (offsetCount - j + 1) * rate;

					this.context.moveTo(x, y - offsetY);
					this.context.lineTo(0, y);
					this.context.lineTo(-x, y - offsetY);
				}
				this.context.moveTo(0, 0);
				this.context.lineTo(0, -this.RADIUS);
				this.context.arc(0, -this.RADIUS - this.topRadius, this.topRadius, Math.PI / 2, Math.PI * 2.5, false);
				this.context.restore();
			}
			this.context.stroke();
			this.context.restore();
		},
		render : function(context){
			context.save();

			if(this.scale > this.THRESHOLD_TRANSPARENCY){
				context.globalAlpha = Math.max(0, (1 - this.scale) / (1 - this.THRESHOLD_TRANSPARENCY));

				if(this.scale > 1 || this.x < -this.radius || this.x > this.width + this.radius || this.y < -this.radius || this.y > this.height + this.radius){
					context.restore();
					return false;
				}
			}
			context.translate(this.x, this.y);
			context.rotate(this.rotate);
			context.scale(this.scale, this.scale);
			context.drawImage(this.canvas, -this.radius, -this.radius);
			context.restore();

			this.x += this.vx;
			this.y += this.vy;
			this.scale *= this.deltaScale;
			this.rotate += this.deltaRotate;
			return true;
		}
	};

	$(function(){
		RENDERER.init();
	});
	console.log("\u002f\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u000d\u000a\u0020\u002a\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u002a\u0009\u0009\u000d\u000a\u0020\u002a\u0020\u0009\u0009\u0009\u0009\u0009\u0009\u0020\u0020\u0020\u0020\u0020\u0020\u4ee3\u7801\u5e93\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u002a\u000d\u000a\u0020\u002a\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0077\u0077\u0077\u002e\u0064\u006d\u0061\u006b\u0075\u002e\u0063\u006f\u006d\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u002a\u000d\u000a\u0020\u002a\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0009\u0009\u0020\u0020\u52aa\u529b\u521b\u5efa\u5b8c\u5584\u3001\u6301\u7eed\u66f4\u65b0\u63d2\u4ef6\u4ee5\u53ca\u6a21\u677f\u0009\u0009\u0009\u002a\u000d\u000a\u0020\u002a\u0020\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u002a\u000d\u000a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002a\u002f");
</script>
</body>
</html>